home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
GameKit
/
gamekit-1
/
GameView.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
11KB
|
435 lines
#import <gamekit/gamekit.h> // Colors
#import <daymisckit/daymisckit.h> // ExtendedApp, etc.
#import <dpsclient/psops.h> // PSsetgray()
#import <dpsclient/wraps.h> // PScompositerect()
#import <libc.h> // for random(), etc.
#import <math.h> // for floor(), etc.
#import <stdio.h> // for standard C file operations
@implementation GameView
#define dragdef const char *dragTypes[3] =\
{NXFilenamePboardType, NXColorPboardType, NULL}
#define dragNum 2
- initFrame:(const NXRect *)frm // designated initializer for a view
{
dragdef;
[super initFrame:frm];
cycles = 0;
srandom(time(0));
demoMode = NO;
grayBorder = YES;
state = GAMEOVER;
demoWait = 0;
doingBorder = NO;
grayBorder = YES;
backColor = NXConvertRGBToColor(0.333, 0.333, 0.333); // dark gray default
backIsColor = YES; // default bg is dark gray...
[self registerForDraggedTypes:dragTypes count:dragNum];
dragOperation = NX_DragOperationNone;
return self;
}
- appDidInit:sender // forwarded by gamebrain
{
if (!controller) controller = [NXApp delegate];
if (!preferences) preferences = [controller preferencesBrain];
if (!scoreKeeper) scoreKeeper = [controller scoreKeeper];
if (!strings) strings = [controller mainStrings];
if (!customSound) customSound = [controller soundPlayer];
[self loadPix];
return self;
}
- loadPix
{
const char *tmpStr;
char *okStr; float r, g, b;
[self allocateGState];
// set background
okStr = malloc(8);
tmpStr = NXGetDefaultValue([NXApp appName], "BackColor");
if (tmpStr) {
backIsColor = NO;
sscanf(tmpStr, "%s %f %f %f", &okStr[0], &r, &g, &b);
backColor = NXConvertRGBToColor(r, g, b);
if (okStr[0] == 'Y') {
backIsColor = YES;
}
}
free(okStr);
// get some buffers to hold our drawings.
buffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
staticBuffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
if (!backIsColor)
[self setBackgroundFile:
NXGetDefaultValue([NXApp appName], "BackGround")
andRemember:NO];
return self;
}
- animate:sender
{ // method to start the animation - called by appDidInit
// set up Animator: (autoUpdate) this handles moving viruses and
// makes sure the columns fall when they should. The animator is
// an object that handles timed entries "smartly".
animator = [[Animator alloc] initChronon:[self speedTime]
adaptation:0.0 target:self
action:@selector(autoUpdate:) autoStart:YES eventMask:0];
return self;
}
- (BOOL)demoMode // if last game was demo
{ return demoMode; }
- (float)speedTime // returns time between animation frames
{ return GRANULARITY; // return delay between clock ticks
} // 0.05 is about as fast as should be used.
- (int)gameState // tell caller our state... if in demo, game is over
{ if (demoMode) return GAMEOVER; return state; }
- (int)realGameState // tell caller our state...may need to really know...
{ return state; }
- getOffset:(NXPoint *)aPoint // returns offset by reference
{
GK_VECTOR_X(aPoint) = offset.x; GK_VECTOR_Y(aPoint) = offset.y;
return self;
}
- setOffset:(const NXPoint *)aPoint // change the offset
{
offset.x = GK_VECTOR_X(aPoint); offset.y = GK_VECTOR_Y(aPoint);
return self;
}
- autoUpdate:sender // called by timed entry to update screen periodically
{ // ALL animation is controlled from here!!!
cycles++;
// you would do updates to various screen objects and
// then do a [self updateSelf:&bounds :1];
return self;
}
- updateSelf:(NXRect *)rects :(int)rectCount // redraws the screen.
{ // it redraws only what has changed since last redraw.
NXPing();
return self;
}
- mouseDown:(NXEvent *)event // handle mouseDown events.
{
[controller pauseGame:self]; // pause/unpause game
return self;
}
- (BOOL)acceptsFirstMouse // let us grab activating mousedowns
{ // 1st click is to become 1st responder, NOT pause/unpause
return NO;
}
- setKey:(int)keyIndex val:(char)keyVal // change key we respond to
{
keys[keyIndex] = keyVal;
return self;
}
- pause:sender // set pause status.
{
paused = YES;
return self;
}
- unpause:sender // remove paused status
{
paused = NO;
return self;
}
- (BOOL)isPaused // tell caller is we're paused
{ return paused; }
- keyDown:(NXEvent *)myevent // handle keyDown events.
{
PSobscurecursor(); // subclasses which override need to do this.
if (myevent->data.key.charSet == NX_ASCIISET &&
(myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0)
{
if (GKKEYCODE == 'p') { // allow pause
if (paused) [controller unpause];
else [controller pause];
} else if (GKKEYCODE == 'n') { // allow new game
[controller startNewGame:self]; // re-start the game
// returns nil if user changes mind...
} else if (paused) { // any keyDown unpauses game (except 'p').
[controller unpause];
}
} else return [super keyDown:myevent];
return self;
}
- (BOOL)acceptsFirstResponder // to grab keyboard events
{ return YES; }
- getPreferences
{
if (!preferences) preferences = [[NXApp delegate] preferencesBrain];
return self;
}
- free // get rid of support objects
{
[animator free];
return [super free];
}
- setUpScreen
{
if ((demoMode)||(doingBorder)) [self display];
return self;
}
- changeBorder:(BOOL)borderOn
{ // move view about in the window & do sizing
NXRect wFrame;
if (borderOn == grayBorder) return self;
if (borderOn) {
[window getFrame:&wFrame];
NXInsetRect(&wFrame, -BEZELSIZE, -BEZELSIZE);
[self moveBy:BEZELSIZE :BEZELSIZE];
[window placeWindowAndDisplay:&wFrame];
} else {
[window getFrame:&wFrame];
NXInsetRect(&wFrame, BEZELSIZE, BEZELSIZE);
[self moveBy:-BEZELSIZE :-BEZELSIZE];
[window placeWindowAndDisplay:&wFrame];
}
grayBorder = borderOn;
return self;
}
- restartGame
{
cycles = 0;
state = NORMALSTATE;
if (demoMode) {
demoMode = NO;
[[self window] setTitle:[strings valueForStringKey:"GameName"]];
}
[scoreKeeper resetScore];
[self getPreferences]; // make sure we're up to date
return self;
}
//// Background handling methods stolen from BreakApp:
- setBackgroundFile:(const char *)fileName andRemember:(BOOL)remember
// This methods allows changing the file used to paint the background of the
// playing field. Set fileName to NULL to revert to the default. Set
// remember to YES if you wish the write the value out in the defaults.
{
[backGround free];
backGround = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
[backGround setBackgroundColor:backColor];
[backGround setScalable:YES];
if (fileName) {
[backGround useFromFile:fileName];
if (remember) {
NXWriteDefault ([NXApp appName], "BackGround", fileName);
}
} else { // default background image
[backGround useFromSection:"BackGround.eps"];
if (remember) {
NXRemoveDefault ([NXApp appName], "BackGround");
}
}
backIsColor = NO;
[self buildBackground];
[self writeColor];
[self display];
return self;
}
- buildBackground { return self; } // for subclass use
// The following two methods allow changing the background image from
// menu items or buttons.
- changeBackground:sender
{
const char *const *types = [NXImage imageFileTypes];
if ([[OpenPanel new] runModalForTypes:types]) {
[self setBackgroundFile:[[OpenPanel new] filename] andRemember:YES];
[self display];
}
return self;
}
- revertBackground:sender
{
backIsColor = NO;
[self setBackgroundFile:NULL andRemember:YES];
[self display];
return self;
}
- loadAnImage:(const char *)imageName
{
char *tempStr = (char *)malloc(MAXPATHLEN);
sprintf(tempStr, "%s/%s", [NXApp appDirectory], imageName);
[self setBackgroundFile:tempStr andRemember:YES];
free(tempStr); [self display];
return self;
}
- back1:sender { return [self loadAnImage:"Back1.eps"]; }
- back2:sender { return [self loadAnImage:"Back2.tiff"]; }
- back3:sender { return [self loadAnImage:"Back3.tiff"]; }
- drawBackground:(NXRect *)rect
// drawBackground: just draws the specified piece of the background by
// compositing from the background image.
{
NXRect tmpRect = *rect;
if (backIsColor) {
NXSetColor(backColor);
NXRectFill(rect);
return self;
}
NX_X(&tmpRect) = floor(NX_X(&tmpRect));
NX_Y(&tmpRect) = floor(NX_Y(&tmpRect));
if (NXDrawingStatus == NX_DRAWING) {
PSsetgray (NX_BLACK);
PScompositerect (NX_X(&tmpRect), NX_Y(&tmpRect),
NX_WIDTH(&tmpRect), NX_HEIGHT(&tmpRect), NX_SOVER);
}
[backGround composite:NX_SOVER fromRect:&tmpRect toPoint:&tmpRect.origin];
return self;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[backGround setSize:&bounds.size];
return self;
}
// deal with drag and drop colors:
- acceptColor:(NXColor)color atPoint:(const NXPoint *)aPoint
{
backIsColor = YES;
backColor = color;
[[self writeColor] update];
return self;
}
- writeColor
{
char def[256];
float r, g, b;
NXConvertColorToRGB(backColor, &r, &g, &b);
sprintf(def, "%s %f %f %f", (backIsColor ? "YES" : "NO"), r, g, b);
NXWriteDefault ([NXApp appName], "BackColor", def);
return self;
}
// these assume that you already locked focus. Thus, when overriding
// these methods, the subclas should lock focus in the static buffer
// before calling the super (this) method.
- rebuildStaticBuffer
{
[self drawBackground:&bounds];
return self;
}
- rebuildStaticAt:(NXRect *)rect
{
[self drawBackground:rect];
return self;
}
// drag and drop an image into the view's background.
// uses 3.0 drag kit stuff
- (NXDragOperation)draggingEntered:sender
{
NXDragOperation sourceMask;
// Ask the sender for its operation mask.
sourceMask = [sender draggingSourceOperationMask];
if (sourceMask & NX_DragOperationCopy)
dragOperation = NX_DragOperationCopy;
else if (sourceMask & NX_DragOperationGeneric)
dragOperation = NX_DragOperationGeneric;
else dragOperation = NX_DragOperationNone;
return dragOperation;
}
- (NXDragOperation)draggingUpdated:sender { return dragOperation; }
- draggingExited:sender { return self; }
- (BOOL)prepareForDragOperation:sender
{ // We do want to accept the dragged image/color.
return YES;
}
- (BOOL)performDragOperation:sender
{
Pasteboard *dragPasteboard = [Pasteboard newName:NXDragPboard];
char *file;
int length;
dragdef;
BOOL foundOne = NO;
if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum]
== NXFilenamePboardType) {
if ([dragPasteboard readType:NXFilenamePboardType
data:&file length:&length]) {
foundOne = YES;
[self setBackgroundFile:file andRemember:YES];
[dragPasteboard deallocatePasteboardData:file length:length];
[NXApp activateSelf:YES];
[window makeKeyAndOrderFront:self];
} }
else if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum]
== NXColorPboardType) {
NXPoint p = [sender draggingLocation];
NXColor c = NXReadColorFromPasteboard([sender draggingPasteboard]);
[self acceptColor:c atPoint:&p];
foundOne = YES;
[NXApp activateSelf:YES];
[window makeKeyAndOrderFront:self];
}
return foundOne;
}
- concludeDragOperation:sender { return self; }
- gameOver // sent by GameBrain
{
state = GAMEOVER;
return self;
}
@end